function [ LMSectBgnInd, LMSectEndInd, LMSectNum ] = findlargemagsects( A, magThresholdType, magThresholdVal, sectLenPreExt, sectLenPostExt, ignoreSectLength, doPlot ) %#codegen
% FINDLARGEMAGSECTS 沿列方向寻找二维矩阵中元素绝对值大于一定阈值的段的起始元素序号和终止元素序号
%
% Input Arguments:
% A: 二维矩阵
% magThresholdType: 标量，指定阈值种类，1表示magThresholdVal为相对于此列元素绝对值最小值的倍数，2表示为相对于此列元素绝对值平均值的倍数，其它表示为绝对阈值，默认为1
% magThresholdVal: 标量，指定阈值数值，参见magThresholdType的帮助，默认为2
% sectLenPreExt, sectLenPostExt: 标量，返回的序号为各大幅值段起始元素序号上减去前者、终止元素序号上加上后者，默认为0
% ignoreSectLength: 标量，忽略长度不大于这一值的大幅值段，默认为0
% doPlot: 逻辑标量，true表示绘制包含分段间隔线的曲线图，绿色分段间隔线表示大幅值段的开始，红色分段间隔线表示大幅值段的结束，间隔线端的数字表示对应A的列数及大幅值段数，默认为true
%
% Output Arguments:
% LMSectBgnInd: X*n（n为A的列数）的数组，X可能大于A中各列实际找到的大幅值段的数量最大值，各列为A对应列的大幅值段的起始元素序号
% LMSectEndInd: Y*n（n为A的列数）的数组，Y可能大于A中各列实际找到的大幅值段的数量最大值，各列为A对应列的大幅值段的终止元素序号
% LMSectNum: 1*n的行向量，各元素为A矩阵对应列中实际找到的大幅值段的数量

if nargin < 2
    magThresholdType = 1;
end
if nargin < 3
    magThresholdVal = 2;
end
if nargin < 4
    sectLenPreExt = 0;
end
if nargin < 5
    sectLenPostExt = 0;
end
if nargin < 6
    ignoreSectLength = 0;
end
if nargin < 7
    doPlot = true;
end

[m, n] = size(A);
% 确定阈值
switch magThresholdType
    case 1
        threshold = min(abs(A), [], 1) * magThresholdVal;
    case 2
        threshold = mean(abs(A), 1) * magThresholdVal;
    otherwise
        threshold = magThresholdVal * ones(1, n);
end
% 确定大幅值段起始和终止元素序号
LMSectBgnInd = zeros(0, n);
LMSectEndInd = zeros(0, n);
coder.varsize('LMSectBgnInd', 'LMSectEndInd', [Inf n], [true false]);
LMSectNum = zeros(1, n);
for j=1:n
    isLastEleBlwThd = true; % 上一个元素是否在阈值以下
    isLMSectEndTBF = false; % 是否已找到大幅值段的起始点而未找到终止点
    for i=1:m
        if abs(A(i, j)) > threshold(1, j)
            if isLastEleBlwThd % 找到大幅值段起始元素
                LMSectNum(1, j) = LMSectNum(1, j) + 1;
                LMSectBgnInd = vertexpand_byref(LMSectBgnInd, LMSectNum(1, j));
                LMSectBgnInd(LMSectNum(1, j), j) = i;
                isLastEleBlwThd = false;
                isLMSectEndTBF = true;
            end
        else
            if ~isLastEleBlwThd % 找到大幅值段终止元素
                if i - LMSectBgnInd(LMSectNum(1, j), j) > ignoreSectLength
                    % 此段长度大于忽略值，引入段长度扩展量
                    LMSectBgnInd(LMSectNum(1, j), j) = LMSectBgnInd(LMSectNum(1, j), j) - sectLenPreExt;
                    LMSectEndInd = vertexpand_byref(LMSectEndInd, LMSectNum(1, j));
                    LMSectEndInd(LMSectNum(1, j), j) = (i-1) + sectLenPostExt;
                else
                    % 此段长度不大于忽略值，大幅值段计数递减
                    LMSectBgnInd(LMSectNum(1, j), j) = 0;
                    LMSectNum(1, j) = LMSectNum(1, j) - 1;
                end
                isLastEleBlwThd = true;
                isLMSectEndTBF = false;
            end
        end
    end
    % 若没有找到最后一个大幅值段的终止元素，则设定此段终止元素序号为A矩阵行数
    if isLMSectEndTBF
        LMSectEndInd = vertexpand_byref(LMSectEndInd, LMSectNum(1, j));
        LMSectEndInd(LMSectNum(1, j), j) = m;
    end
end

% 当序号扩展后，可能产生前一段的终点在后一段起点之后的情况，需要将重叠的段合并
for j=1:n
    bgnInd = LMSectBgnInd(:, j); % 删除元素操作需要按列处理
    endInd = LMSectEndInd(:, j);
    i = 2;
    while (i<=length(bgnInd)) && ((i-1)<=length(endInd))
        if bgnInd(i, 1) ~= 0
            if (i-1>0) && (bgnInd(i, 1)<=endInd(i-1, 1))
                bgnInd(i) = []; % NOTE: 使用线性索引
                endInd(i-1) = [];
                LMSectNum(1, j) = LMSectNum(1, j) - 1;
            else
                i = i + 1;
            end
        else
            break;
        end
    end
    LMSectBgnInd(:, j) = 0;
    LMSectBgnInd(1:length(bgnInd), j) = bgnInd;
    LMSectEndInd(:, j) = 0;
    LMSectEndInd(1:length(endInd), j) = endInd;
end

% 绘图
if doPlot
    preparefig('findlargemagsects');
    plot(A);
    hold on;
    yLimit = ylim;
    for j=1:n
        for i=1:LMSectNum(1, j)
            line([LMSectBgnInd(i, j) LMSectBgnInd(i, j)], ylim, 'LineStyle', '-.', 'Color', 'g', 'LineWidth', 2);
            text(LMSectBgnInd(i, j), yLimit(1), [num2str(j) '-' num2str(i)], 'Color', 'g', 'FontWeight', 'bold');
            line([LMSectEndInd(i, j) LMSectEndInd(i, j)], ylim, 'LineStyle', '-.', 'Color', 'r', 'LineWidth', 2);
            text(LMSectEndInd(i, j), yLimit(2), [num2str(j) '-' num2str(i)], 'Color', 'r', 'FontWeight', 'bold');
        end
    end
    hold off;
end